<script setup lang="ts">
import { ref, reactive, onMounted, nextTick } from "vue";
import {
  ArrowDown,
  WarningFilled,
  QuestionFilled,
} from "@element-plus/icons-vue";
import { FormInstance,ElMessage } from "element-plus";
import { Protocol, Direction, Rule, Target, RuleDelete } from "./interface";
import axios, { AxiosError } from "axios";


// ============= API ============
const addRule = async (rule: Rule) => {
  console.log("addRule");

  const request = axios.post("http://127.0.0.1:8095/add-rule", "rule="+JSON.stringify(rule))

  request.then((res) => {
    console.log(res.data);
    if(res.data == 'succeed'){
      ElMessage({
        message:"添加成功",
        type:'success'
      })
      refreshRules()
    }else{
      ElMessage.error('Oops 出错了：'+ res.data)
    }
  });

  request.catch((err:AxiosError)=>{
     ElMessage.error('Oops 出错了：'+ err.message)
  })

};

const deleteRule = async (ruleDelete: RuleDelete) => {

  console.log("delete-rule", ruleDelete);

  const request = axios.post("http://127.0.0.1:8095/delete-rule", "rule="+JSON.stringify(ruleDelete))

  request.then((res) => {
    console.log(res.data);
    if(res.data == 'succeed'){
      ElMessage({
        message:"删除成功",
        type:'success'
      })

      refreshRules()
    }else{
      ElMessage.error('Oops 出错了：'+ res.data)
    }
  });

  request.catch((err:AxiosError)=>{
     ElMessage.error('Oops 出错了：'+ err.message)
  })
  
};


const refreshRules = async () => {
  console.log("refresh-rules");
  const request = axios.get("http://127.0.0.1:8095/refresh-rules")

  request.then((res) => {
    if(res.data != 'error'){
      iptables.value = [];
      iptables.value = res.data;
      console.log(iptables.value)

      ElMessage({
        message:"获取列表成功",
        type:'success'
      })

      refreshTable()
    }
  });

  request.catch((err:AxiosError)=>{
     ElMessage.error('Oops 出错了：'+ err.message)
  })
  
};

// ======= data =======
const showTable = ref(true)
const iptables:any = ref([])
onMounted(()=>{
  refreshRules();
})

const refreshTable = ()=>{
    showTable.value = false;
    nextTick(()=>{
      showTable.value = true
    })
}

// ======= form =======
const direction = ref(Direction.INPUT);

const configForm = reactive({
  target: Target.ACCEPT,
  protocol: Protocol.TCP,
  num: 1,
  sport: -1, //端口
  dport: -1, //
  src: "0.0.0.0/0", //CIDR
  dst: "0.0.0.0/0",
}); //储存配置表单

const formRef = ref<FormInstance>();

const showForm = ref(false);
const handleCommand = (command: string | number | object) => {
  switch (command) {
    case "newRule":
      showForm.value = true;
      break;
      
    case "refreshRules":
      refreshRules();
      break;
  }
};

//========= form ==========
const addNewRule = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log("submit!");
      addRule(getRule());
    } else {
      console.log("error submit!", fields);
    }
    formRef.value?.resetFields()
    showForm.value = false
    
  });
};

const getRule = (): Rule => {
  let rule = {
    num: configForm.num,
    direction: direction.value as number,
    target: configForm.target,
    protocol: configForm.protocol,
    src: configForm.src,
    sport: configForm.sport,
    dst: configForm.dst,
    dport: configForm.dport,
  };
  console.log(rule);
  return rule;
};

</script>

<template>
  <div id="container">
    <el-contianer>
      <el-row>
        <el-col :span="6">
          <el-popover
            placement="bottom-end"
            title="Tips"
            :width="200"
            trigger="hover"
          >
            <template #reference>
              <el-link id="title">
                防火墙配置
                <el-divider direction="vertical" border-style="dashed" />
                <el-icon><question-filled /></el-icon>
              </el-link>
            </template>

            <template #default>
              <div
                class="demo-rich-conent"
                style="display: flex; gap: 16px; flex-direction: column"
              >
                <div>
                  <p
                    class="demo-rich-content__name"
                    style="margin: 0; font-weight: 500"
                  >
                    基于iptables的简易IPV4防火墙
                  </p>
                  <p
                    class="demo-rich-content__mention"
                    style="
                      margin: 0;
                      font-size: 14px;
                      color: var(--el-color-info);
                    "
                  >
                    @group-8
                  </p>
                </div>

                <p class="demo-rich-content__desc" style="margin: 0">
                  ip：0.0.0.0/0 for any
                </p>
                <p class="demo-rich-content__desc" style="margin: 0">
                  port：-1 for any
                </p>
              </div>
            </template>
          </el-popover>
        </el-col>
        <el-col :span="2"> </el-col>

        <el-col :span="4" :offset="20">
          <el-dropdown size="large" @command="handleCommand">
            <span class="el-dropdown-link">
              选项
              <el-icon class="el-icon--right">
                <arrow-down />
              </el-icon>
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="newRule">新建规则</el-dropdown-item>
                <el-dropdown-item divided command="refreshRules">刷新规则</el-dropdown-item>
                <el-dropdown-item divided>导入规则</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </el-col>
      </el-row>

      <el-main>
        <el-form
          v-if="showForm"
          ref="formRef"
          :model="configForm"
          label-position="top"
        >
          <el-row :gutter="5">
            <el-col :span="3">
              <el-form-item
                label="序号"
                prop="num"
                :rules="[{ type: 'number', message: 'port must be a number' }]"
              >
                <el-input v-model.number="configForm.num"></el-input>
              </el-form-item>
            </el-col>

            <el-col :span="5">
              <el-form-item label="target策略(-j)" prop="target">
                <el-select v-model="configForm.target">
                  <el-option label="允许" :value="Target.ACCEPT"></el-option>
                  <el-option label="拒绝" :value="Target.REJECT"></el-option>
                </el-select>
              </el-form-item>
            </el-col>

            <el-col :span="5">
              <el-form-item label="Protocol协议(-p)" prop="protocol">
                <el-select v-model="configForm.protocol">
                  <el-option label="TCP" :value="Protocol.TCP"></el-option>
                  <el-option label="UDP" :value="Protocol.UDP"></el-option>
                  <el-option label="ICMP" :value="Protocol.ICMP_V4"></el-option>
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="3">
            <el-col :span="7">
              <el-form-item label="源ip(-s)" prop="src">
                <el-input
                  v-model="configForm.src"
                  placeholder="CIDR"
                  clearable
                />
              </el-form-item>
            </el-col>

            <el-col :span="6">
              <el-form-item label="sport源端口(--sport)" prop="sport">
                <el-input-number
                  v-model="configForm.sport"
                  :min="-1"
                  :max="65535"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="3">
            <el-col :span="7">
              <el-form-item label="目的ip(-d)" prop="dst">
                <el-input
                  v-model="configForm.dst"
                  placeholder="CIDR"
                  clearable
                />
              </el-form-item>
            </el-col>

            <el-col :span="6">
              <el-form-item label="dport目的端口(--dport)" prop="dport">
                <el-input-number
                  v-model="configForm.dport"
                  :min="-1"
                  :max="65535"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <!-- <el-row :gutter="3">
            <el-col :span="6">
              <el-form-item label="起始时间" prop="startTime">
                <el-time-select
                  v-model="configForm.startTime"
                  start="00:00"
                  end="23:59"
                />
              </el-form-item>
            </el-col>

            <el-col :span="6">
              <el-form-item label="结束时间" prop="endTime">
                <el-time-select
                  v-model="configForm.endTime"
                  start="00:00"
                  end="23:59"
                />
              </el-form-item>
            </el-col>
          </el-row> -->

          <el-form-item>
            <el-button type="primary" @click="addNewRule(formRef)"
              >确认</el-button
            >

            <el-button
              @click="
                showForm = false;
                formRef?.resetFields();
              "
              >取消</el-button
            >
          </el-form-item>
          <el-divider />
        </el-form>

        <!-- in / out -->

        <el-row>
          <el-col :span="24">
            <el-tabs v-model="direction" class="DirectionTabs">
              <el-tab-pane label="入方向INPUT"  :name="Direction.INPUT">
                <el-table :data="iptables[0]"  v-if='showTable' border stripe style="width: 100%">
                  <el-table-column type="index" label="序号" />
                  <el-table-column prop="target" label="策略" />
                  <el-table-column prop="prot" label="协议" />
                  <el-table-column prop="source" label="源地址" />
                  <el-table-column prop="spt" label="源端口" />

                  <el-table-column prop="destination" label="目的地址" />
                  <el-table-column prop="dpt" label="目的端口" />

                  <el-table-column fixed="right" label="编辑" width="75">
                    <template #default="scope">
                      <el-popconfirm
                        confirm-button-text="Yes"
                        cancel-button-text="No"
                        :icon="WarningFilled"
                        icon-color="#626AEF"
                        title="Are you sure to delete this?"
                        @confirm="
                          deleteRule({
                            chain: direction,
                            num: (scope.$index )+ 1,
                          })
                        "
                      >
                        <template #reference>
                          <el-button text size="small" type="danger">
                            删除
                          </el-button>
                        </template>
                      </el-popconfirm>
                    </template>
                  </el-table-column>
                </el-table>
              </el-tab-pane>

              <el-tab-pane label="出方向OUPUT" :name="Direction.OUTPUT">
                <el-table :data="iptables[1]"  v-if='showTable' border stripe style="width: 100%">
                  <el-table-column type="index" label="序号" />
                  <el-table-column prop="target" label="策略" />
                  <el-table-column prop="prot" label="协议" />
                  <el-table-column prop="source" label="源地址" />
                  <el-table-column prop="spt" label="源端口" />

                  <el-table-column prop="destination" label="目的地址" />
                  <el-table-column prop="dpt" label="目的端口" />

                  <el-table-column fixed="right" label="编辑" width="75">
                    <template #default="scope">
                      <el-popconfirm
                        confirm-button-text="Yes"
                        cancel-button-text="No"
                        :icon="WarningFilled"
                        icon-color="#626AEF"
                        title="Are you sure to delete this?"
                        @confirm="
                          deleteRule({
                            chain: direction,
                            num: (scope.$index) + 1,
                          })
                        "
                      >
                        <template #reference>
                          <el-button text size="small" type="danger">
                            删除
                          </el-button>
                        </template>
                      </el-popconfirm>
                    </template>
                  </el-table-column>
                </el-table>
              </el-tab-pane>
            </el-tabs>

          </el-col>
        </el-row>

      </el-main>
    </el-contianer>
  </div>
</template>


<!-- <script lang="ts">
//table
const iptables_sample = [
  [
    // IN
    {
      target: "允许",
      protocol: "TCP",
      sport: -1,
      dport: 8000,
      src: "0.0.0.0 /0",
      dst: "0.0.0.0 /0",
    },
    {
      target: "拒绝",
      protocol: "ICMP",
      sport: -1,
      dport: 8000,
      src: "172.64.24.1 /20",
      dst: "0.0.0.0 /0",
    },
  ],

  [
    //OUT
    {
      direction: 1,
      target: "拒绝",
      protocol: "UDP",
      sport: -1,
      dport: -1,
      src: "192.168.100.110 /24",
      dst: "0.0.0.0 /0",
    },
    {
      direction: 1,
      target: "拒绝",
      protocol: "ICMP",
      sport: -1,
      dport: -1,
      src: "0.0.0.0 /0",
      dst: "172.64.24.1 /24",
    },
  ],
];

console.log(iptables_sample);

const ProtocolMap: {
  [index: number]: { Protocol: string };
} = {};
ProtocolMap[1] = { Protocol: "ICMP" };
ProtocolMap[6] = { Protocol: "TCP" };
ProtocolMap[17] = { Protocol: "UDP" };
</script> -->

<style>
#app {
  font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
    "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  /* margin-top: 60px;
  margin-left: 20%;
  margin-right: 20%; */
}

#title {
  margin-top: 13%;
  /* margin-left: 6%; */
  text-align: left;
  font-size: x-large;
  font-weight: bolder;
}

#container {
  margin-left: 13%;
  margin-right: 13%;
}

#newRuleButtons {
  margin-top: 30px;
}
</style>

<style scoped>
.example-showcase .el-dropdown-link {
  cursor: pointer;
  color: var(--el-color-primary);
  display: flex;
  align-items: center;
}
</style>
